package com.plugins.activity;


import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.media.RingtoneManager;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.text.TextUtils;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;

import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.NotificationCompat;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import com.plugins.App;
import com.plugins.R;
import com.plugins.pluginlib.broadcast.BroadMessage;
import com.plugins.pluginlib.internal.IPluginManager;
import com.plugins.task.Task;
import com.plugins.task.TaskManager;
import com.plugins.utils.CustomClassLoader;
import com.plugins.utils.FileDownloader;
import com.plugins.utils.FileUtil;
import com.plugins.utils.plugin.PluginsManager;
import com.plugins.utils.plugin.bean.PluginInfo;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.security.SecureRandom;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import dalvik.system.DexClassLoader;
import dalvik.system.PathClassLoader;

public class MainActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        TextView textView = findViewById(R.id.btn_refresh);
        textView.setOnClickListener(view -> {
            getList();
        });
        getList();
    }

    private String url = "https://youdelu.fun:10002/down/tSP2H7uQDi6p";
    private void getList(){
        Task task = new Task() {
            @Override
            public Task doTask() {
                try {
                    Document doc = Jsoup.connect(url).get();
                    List<FileData> fileList = parseTable(doc);
                    setResult(fileList);
                } catch (Exception e) {
                    e.printStackTrace();
                }
                return this;
            }
        };
        TaskManager.getInstance().exec(task, task1 -> {
            List<FileData> fileList = task1.getResult();
            putList(fileList);
        });
    }

    private void putList(List<FileData>  fileList){
        LinearLayout layout = findViewById(R.id.ll_main);
        layout.removeAllViews();
        for (FileData file : fileList) {
            View item = LayoutInflater.from(this).inflate(R.layout.main_item, null);
            TextView name = item.findViewById(R.id.tv_name);
            name.setText("插件名称:"+file.fileName);
            TextView count = item.findViewById(R.id.tv_count);
            count.setText("下载次数:"+file.downloadCount+"");
            TextView size = item.findViewById(R.id.tv_size);
            size.setText("插件大小:"+file.size);
            Button download = item.findViewById(R.id.btn_download);
            Button open = item.findViewById(R.id.btn_open);
            open.setOnClickListener(view -> {
                if(file.dataPath.endsWith(".apk")) {
                    showOpenDialog(file.dataPath);
                }else if(file.dataPath.endsWith(".dex")){
                    if(file.dataPath.endsWith("Test.dex")){
                        openClassFile(file.dataPath,item);
                    }else{
                        openDexFile(file.dataPath,item);
                    }
                }
            });
            Button del = item.findViewById(R.id.btn_del);
            del.setOnClickListener(view -> {
                //删除文件
                FileUtil.removeFile(FileUtil.getPath()+file.dataPath);
                //移除插件环境
                PluginsManager.getInstance().removePlugin(file.dataPath);
                //刷新列表
                getList();
            });
            if(FileUtil.checkFileExists(FileUtil.getPath()+file.dataPath)){
                download.setText("已下载");
                TextView detail = item.findViewById(R.id.tv_detail);
                if(file.dataPath.endsWith(".apk")) {
                    File pluginFile = new File(FileUtil.getPath() + file.dataPath);
                    //已下载 获取插件的详细信息
                    PluginInfo pluginInfo = PluginsManager.getInstance().getPluginInfo(pluginFile);
                    String text = "";
                    text += "保存路径:" + pluginInfo.getPluginPath() + "\n";
                    text += "插件包名:" + pluginInfo.getPackageName() + "\n";
                    text += "插件版本号:" + pluginInfo.getVersionCode() + "\n";
                    text += "插件版本:" + pluginInfo.getVersionName() + "\n";
                    detail.setText(text);
                }else if(file.dataPath.endsWith(".dex")){
                    detail.setText("文件路径"+FileUtil.getPath() + file.dataPath);
                }
            }else{
                download.setText("下载插件");
            }
            download.setOnClickListener(view -> {
                download(download,file.downloadLink,file.dataPath);
            });
            layout.addView(item);
        }
    }

    /**
     * 加载class文件，并执行里面的方法
     * @param pluginName
     */
    private void openClassFile(String pluginName,View item){
        try {
            // class文件路径
            PathClassLoader classLoader = new PathClassLoader(FileUtil.getPath()+pluginName, getClassLoader());
            // 加载class文件
            Class<?> loadedClass;
            try {
                loadedClass = classLoader.loadClass("Test");
            } catch (ClassNotFoundException e) {
                throw new RuntimeException(e);
            }
            Object instance = loadedClass.newInstance();
            // 调用getKey方法
            Method getKeyMethod = loadedClass.getMethod("getKey");
            String keyResult = (String) getKeyMethod.invoke(instance);
            String result = "执行Class里面的方法:\n";
            result+="getKey="+keyResult+"\n";

            // 调用sum方法
            Method sumMethod = loadedClass.getMethod("sum", int.class, int.class);
            String sumResult = (String) sumMethod.invoke(instance, 12, 333);
            result+="sum="+sumResult+"\n";
            TextView textView = item.findViewById(R.id.tv_detail);
            textView.append(result);
        } catch (NoSuchMethodException | IllegalAccessException | InstantiationException |
                 InvocationTargetException e) {
            e.printStackTrace();
        }
    }

    /**
     * 加载dex文件，并执行里面的方法
     * @param pluginName
     */
    private void openDexFile(String pluginName,View item){
        try {
            // 使用DexClassLoader加载插件的class文件
            DexClassLoader dexClassLoader = new DexClassLoader(FileUtil.getPath()+pluginName, getFilesDir().getAbsolutePath(), null, getClassLoader());
            Class<?> pluginClass = null;
            try {
                pluginClass = Class.forName("com.plugins.activity.Test", true, dexClassLoader);
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            }

            // 创建插件的实例并调用方法
            Object pluginInstance = pluginClass.newInstance();

            // 调用sum方法
            Method sumMethod = pluginClass.getMethod("sum", int.class, int.class);
            String sumResult = (String) sumMethod.invoke(pluginInstance, 23, 34);
            String result = "执行Dex里面的方法:\n";
            result+="sum="+sumResult+"\n";
            TextView textView = item.findViewById(R.id.tv_detail);
            textView.append(result);

        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    /**
     * 输入参数
     * @param pluginName
     */
    private void showOpenDialog(String pluginName){
        AlertDialog.Builder builder = new AlertDialog.Builder(this);
        builder.setTitle("请输入传参");
        final EditText input = new EditText(this);
        input.setHeight(200);
        input.setHint("请输入参数");
        input.setText("[{\"key\":\"value\"}]");
        builder.setView(input);
        builder.setPositiveButton("确认", (dialog, which) -> {
            String inputData = input.getText().toString();
            open(pluginName,inputData);
        });
        builder.setNegativeButton("取消", (dialog, which) -> {
            dialog.cancel(); // 关闭弹窗
        });
        builder.show();

    }

    /**
     * 打开插件
     * @param pluginName
     */
    private void open(String pluginName,String json){
        BroadMessage broadMessage = new BroadMessage();
        broadMessage.setCommand("test");
        List<Map<String, Object>> list = JSON.parseObject(json, new TypeReference<List<Map<String, Object>>>() {});
        Map<String, Object> map = list.get(0);
        broadMessage.setParam(map);
        PluginsManager.getInstance().openPlugin(pluginName, broadMessage, receiver -> {
            String msg = "";
            msg+="command:"+receiver.getCommand()+"\n";
            msg+="status:"+receiver.getStatus()+"\n";
            msg+="message:"+receiver.getMessage()+"\n";
            msg+="param:"+JSON.toJSONString(receiver.getParam())+"\n";
            msg+="result:"+JSON.toJSONString(receiver.getResult())+"\n";
            msg+="data:"+JSON.toJSONString(receiver.getData())+"\n";
            //弹一条系统通知
            sendNotifacation("主应用通知",msg);
            //如果是插件发过来的 把这条消息发回给插件
            if("来自插件的消息".equals(receiver.getCommand())) {
                BroadMessage broadMessage2 = new BroadMessage();
                broadMessage2.setCommand("宿主收到插件发过来的参数，并且又返回给插件，看看插件有没有收到");
                broadMessage2.setMessage(msg);
                try {
                    PluginsManager.getInstance().sendMessage(pluginName, broadMessage2);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
    }

    /**
     * 下载插件
     * @param button
     * @param url
     * @param fileName
     */
    private void download(Button button, String url, String fileName){
        button.setEnabled(false);
        FileDownloader fileDownloader = new FileDownloader();
        url = "https://youdelu.fun:10002"+url;
        fileDownloader.downloadFile(url+fileName,FileUtil.getPath()+fileName, new FileDownloader.DownloadCallback() {
            @Override
            public void onProgressUpdate(int progress) {
                // 更新UI显示下载进度
                button.setText("进度:"+progress+"%");
            }

            @Override
            public void onDownloadComplete() {
                // 下载完成处理
                button.setEnabled(true);
                getList();
                Toast.makeText(MainActivity.this,"下载成功",Toast.LENGTH_SHORT).show();
            }

            @Override
            public void onDownloadFailed(String errorMessage) {
                // 下载失败处理
                button.setEnabled(true);
                getList();
                Toast.makeText(MainActivity.this,"下载失败",Toast.LENGTH_SHORT).show();
            }
        });

    }

    /**
     * 解析html里的数据
     * @param doc
     * @return
     */
    public static List<FileData> parseTable(Document doc) {
        List<FileData> fileList = new ArrayList<>();
        Element table = doc.select("table").first();
        Elements rows = table.select("tr");
        for (int i = 1; i < rows.size(); i++) {
            Element row = rows.get(i);
            Elements cols = row.select("td");
            String fileName = cols.get(0).select("span").text();
            int downloadCount = Integer.parseInt(cols.get(1).select("span").text());
            String size = cols.get(2).select("span").text();
            String downloadLink = cols.get(3).select("a").attr("href");
            String dataPath = cols.get(3).select("a").attr("data-path");
            fileList.add(new FileData(fileName, downloadCount, size, downloadLink,dataPath));
        }
        return fileList;
    }

    /**
     * 插件信息
     */
    static class FileData {
        String fileName;
        int downloadCount;
        String size;
        String downloadLink;
        String dataPath;

        public FileData(String fileName, int downloadCount, String size, String downloadLink,String dataPath) {
            this.fileName = fileName;
            this.downloadCount = downloadCount;
            this.size = size;
            this.downloadLink = downloadLink;
            this.dataPath = dataPath;
        }

        @Override
        public String toString() {
            return "FileData{" +
                    "fileName='" + fileName + '\'' +
                    ", downloadCount=" + downloadCount +
                    ", size='" + size + '\'' +
                    ", downloadLink='" + downloadLink+dataPath + '\'' +
                    '}';
        }
    }

    /**
     * 发送通知
     */
    private int NOTIFICATION_ID = 100;
    private final String CHANNEL_ID = App.getApp().getPackageName();
    private final String CHANNEL_NAME = App.getApp().getPackageName() + "_Notification";
    private void sendNotifacation(String title,String content) {
        Bitmap iconBitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.ic_launcher);
        Uri defaultSoundUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
        NotificationManager notificationManager = (NotificationManager) App.getApp().getSystemService(Context.NOTIFICATION_SERVICE);
        NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(App.getApp());
        mBuilder.setSmallIcon(R.mipmap.ic_launcher_round).
                setContentTitle(title).
                setContentText(content).
                setAutoCancel(true).
                setLargeIcon(iconBitmap).
                setSound(defaultSoundUri);
        NotificationCompat.BigTextStyle bigTextStyle = new NotificationCompat.BigTextStyle();
        bigTextStyle.bigText(content);
        bigTextStyle.setBigContentTitle(title);
        mBuilder.setStyle(bigTextStyle);
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            NotificationChannel channel = new NotificationChannel(CHANNEL_ID, CHANNEL_NAME, NotificationManager.IMPORTANCE_DEFAULT);
            mBuilder.setChannelId(CHANNEL_ID);
            notificationManager.createNotificationChannel(channel);
        }
        notificationManager.notify(NOTIFICATION_ID++, mBuilder.build());
    }
}